package thrift

import (
	// "encoding/binary"
	"context"
	"fmt"
	"net"
	"os"
	"reflect"
	"web/gen-go/hbase"

	//    "strconv"
	"time"

	"github.com/apache/thrift/lib/go/thrift"
)

const (
	HOST       = "nn1.hadoop"
	PORT       = "9090"
	TESTRECORD = 10
)

var (
	ctx context.Context = nil
)

func Thrift() {

	ctx = context.Background()
	startTime := currentTimeMillis()
	logformatstr_ := "----%s\n"
	logformatstr := "----%s Cut times :%d-%d=%d MS \n\n"
	logformattitle := "create connection "
	rowkey := "row_154092606735603"
	temptable := "tb_test"
	protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
	transport, err := thrift.NewTSocket(net.JoinHostPort(HOST, PORT))
	if err != nil {
		fmt.Fprintln(os.Stderr, "error resolving address:", err)
		os.Exit(1)
	}
	client := hbase.NewTHBaseServiceClientFactory(transport, protocolFactory)
	if err := transport.Open(); err != nil {
		fmt.Fprintln(os.Stderr, "Error opening socket to "+HOST+":"+PORT, " ", err)
		os.Exit(1)
	}
	tmpendTime := currentTimeMillis()
	fmt.Printf(logformatstr, logformattitle, tmpendTime, startTime, (tmpendTime - startTime))
	defer transport.Close()

	//--------------Exists--------------------
	logformattitle = " call exist method : "
	fmt.Printf(logformatstr_, logformattitle)
	tmpstartTime := currentTimeMillis()
	//
	isexists, err := (client.Exists(ctx, []byte(temptable), &hbase.TGet{Row: []byte(rowkey)}))
	fmt.Printf("rowkey{%s} in table{%s} Exists:%t\t", rowkey, temptable, isexists)
	if err != nil {
		fmt.Printf("Exists err:%s\n", err)
	}
	fmt.Println("")
	tmpendTime = currentTimeMillis()
	fmt.Printf(logformatstr, logformattitle, tmpendTime, tmpstartTime, (tmpendTime - tmpstartTime))

	//------------Get---------------
	logformattitle = "call get method to retrieve data:"
	fmt.Printf(logformatstr_, logformattitle)
	tmpstartTime = currentTimeMillis()
	//
	result, err := (client.Get(ctx, []byte(temptable), &hbase.TGet{Row: []byte(rowkey)}))
	if err != nil {
		fmt.Printf("Get err:%s\n", err)
	} else {
		fmt.Println("Rowkey:" + string(result.Row))
		for _, cv := range result.ColumnValues {
			printStruct(cv)
		}
	}
	tmpendTime = currentTimeMillis()
	fmt.Printf(logformatstr, logformattitle, tmpendTime, tmpstartTime, (tmpendTime - tmpstartTime))

	//--------------put------------------------
	logformattitle = "call Put method to write data : "
	rowkey = "row_154092606735604"
	fmt.Printf(logformatstr_, logformattitle)
	tmpstartTime = currentTimeMillis()
	cvarr := []*hbase.TColumnValue{
		&hbase.TColumnValue{
			Family:    []byte("cf"),
			Qualifier: []byte("title"),
			Value:     []byte("welcome to lesorb.cn")},
		&hbase.TColumnValue{
			Family:    []byte("cf"),
			Qualifier: []byte("content"),
			Value:     []byte("welcome, why are u here!")},
		&hbase.TColumnValue{
			Family:    []byte("cf"),
			Qualifier: []byte("create"),
			Value:     []byte("user5")},
		&hbase.TColumnValue{
			Family:    []byte("cf"),
			Qualifier: []byte("create_time"),
			Value:     []byte("2017-03-21 16:17:26")},
		&hbase.TColumnValue{
			Family:    []byte("cf"),
			Qualifier: []byte("tags"),
			Value:     []byte("welcome,lesorb")}}
	temptput := hbase.TPut{Row: []byte(rowkey), ColumnValues: cvarr}
	err = client.Put(ctx, []byte(temptable), &temptput)
	if err != nil {
		fmt.Printf("Put err:%s\n", err)
	} else {
		fmt.Println("Put done")
	}
	tmpendTime = currentTimeMillis()
	fmt.Printf(logformatstr, logformattitle, tmpendTime, tmpstartTime, (tmpendTime - tmpstartTime))

	//------------DeleteSingle------------
	logformattitle = "call DeleteSingle method to delete a data: "
	fmt.Printf(logformatstr_, logformattitle)
	tmpstartTime = currentTimeMillis()
	tdelete := hbase.TDelete{Row: []byte(rowkey)}
	err = client.DeleteSingle(ctx, []byte(temptable), &tdelete)
	if err != nil {
		fmt.Printf("DeleteSingle err:%s\n", err)
	} else {
		fmt.Printf("DeleteSingel done\n")
	}

	tmpendTime = currentTimeMillis()
	fmt.Printf(logformatstr, logformattitle, tmpendTime, tmpstartTime, (tmpendTime - tmpstartTime))

}

//struct
func printStruct(cv interface{}) {
	switch reflect.ValueOf(cv).Interface().(type) {
	case *hbase.TColumnValue:
		s := reflect.ValueOf(cv).Elem()
		typeOfT := s.Type()
		//get Thrift2 field
		for i := 0; i < s.NumField(); i++ {
			f := s.Field(i)
			fileldformatstr := "\t%d: %s(%s)= %v\n"
			switch f.Interface().(type) {
			case []uint8:
				fmt.Printf(fileldformatstr, i, typeOfT.Field(i).Name, f.Type(), string(f.Interface().([]uint8)))
			case *int64:
				var tempint64 int64
				if f.Interface().(*int64) == nil {
					tempint64 = 0
				} else {
					tempint64 = *f.Interface().(*int64)
				}
				fmt.Printf(fileldformatstr, i, typeOfT.Field(i).Name, f.Type(), tempint64)
			default:
				fmt.Printf("I don't know")
			}
		}
	default:
		fmt.Printf("I don't know")
		fmt.Print(reflect.ValueOf(cv))
	}
}
func currentTimeMillis() int64 {
	return time.Now().UnixNano() / 1000000
}
